<?php

namespace common\components\wechat;

use Yii;
use yii\base\InvalidConfigException;
use common\components\wechat\components\BasePayment;
use common\components\wechat\mp\Mmpaymkttransfers;
use yii\helpers\ArrayHelper;
use common\helpers\StringHelper;
use common\components\wechat\mp\Refund;

/**
 * 微信支付
 * 注:部分功能因API的整体和功能性, 拆分为单独的类调用请查看compoents/mp文件夹
 * @package calmez\wechat\sdk
 */
class PaymentWechat extends BasePayment {

    /**
     * 公众账号ID
     * 微信分配的公众账号ID（企业号corpid即为此appId）
     * @var String(32)
     */
    public $appid;

    /**
     * 密钥
     * @var String(32)
     */
    public $secret;

    /**
     * 商户号
     * 微信支付分配的商户号
     * @var String(32)
     */
    public $mch_id;

    /**
     * 合作商户密钥
     * @var String(32)
     */
    public $partner_key;

    /**
     * @inheritdoc
     * @throws InvalidConfigException
     */
    public function init() {
        if ($this->appid === null) {
            throw new InvalidConfigException('The "appid" property must be set.');
        }
    }

    const UNIFIED_ORDER_URL = '/pay/unifiedorder';

    /**
     * 微信预下单
     * @param array $config
     * @return type
     */
    public function prepay($config) {
        if (!isset($config['class'])) {
            $config['class'] = 'common\components\wechat\mp\UnifiedOrder';
        }
        $this->setTransport($config);
        $attributes = array_filter($this->transport->getAttributes());
        $attributes['sign'] = parent::generateSignature($attributes, $this->partner_key);

        $post = $this->xml($attributes);
        $response = $this->httpRaw(self::UNIFIED_ORDER_URL, $post);
        Yii::error($response, __METHOD__);
        $prepayData = $this->parseRequestXml($response);
        $prepayId = ArrayHelper::getValue($prepayData, 'prepay_id');
        if (!$prepayId) {
            Yii::error([
                'result' => $prepayData,
                'xml' => $post,
                'partner_key' => $this->partner_key,
                'attributes' => $attributes
            ], __METHOD__);
            return [];
        }

        $openid = ArrayHelper::getValue($attributes, 'openid');
        $data = [];
        if ($openid) {
            $data = [
                'appId' => $this->appid,
                'timeStamp' => strval(time()),
                'nonceStr' => StringHelper::random(32),
                'package' => 'prepay_id=' . $prepayId,
                'signType' => 'MD5',
            ];
            $data['paySign'] = static::generateSignature($data, $this->partner_key);
        } else {
            $data = [
                'appid' => $this->appid,
                'partnerid' => $this->mch_id,
                'prepayid' => $prepayId,
                'package' => 'Sign=WXPay',
                'noncestr' => StringHelper::random(32),
                'timestamp' => strval(time()),
            ];
            $data['sign'] = static::generateSignature($data, $this->partner_key);
        }

        Yii::error($data);

        return $data;
    }

    /**
     * 微信扫码支付
     * @param array $config
     * @return type
     */
    public function native($config) {
        if (!isset($config['class'])) {
            $config['class'] = 'common\components\wechat\mp\UnifiedOrder';
        }
        $this->setTransport($config);
        $attributes = array_filter($this->transport->getAttributes());
        $attributes['sign'] = parent::generateSignature($attributes, $this->partner_key);

        $post = $this->xml($attributes);
        $response = $this->httpRaw(self::UNIFIED_ORDER_URL, $post);
        Yii::error($response, __METHOD__);
        $prepayData = $this->parseRequestXml($response);
        return ArrayHelper::getValue($prepayData, 'code_url');
    }

    const REFUND_URL = '/secapi/pay/refund';

    /**
     * 微信退款
     * @param array $config
     * @return type
     */
    public function refund($config) {
        if (!isset($config['class'])) {
            $config['class'] = Refund::class;
        }
        Yii::error([
            'refundConfig' => $config
        ]);
        $this->setTransport($config);
        $transport = $this->transport;
        Yii::error([
            'getAttributes' => $transport->getAttributes()
        ]);
        $attributes = array_filter($transport->getAttributes());
        $attributes['sign'] = parent::generateSignature($attributes, $this->partner_key);
        Yii::error([
            '$attributes' => $attributes
        ]);
        $post = $this->xml($attributes);
        Yii::error([
            '$post' => $post
        ]);
        $response = $this->curl_post_ssl(self::REFUND_URL, $post);
        Yii::error([
            self::REFUND_URL,
            '$response' => $response
        ]);
        return $this->parseRequestXml($response);
    }

    const REFUND_QUERY_URL = '/secapi/pay/refundquery';

    public function refundQuery($config) {
        if (!isset($config['class'])) {
            $config['class'] = 'common\components\wechat\mp\Refund';
        }
        $this->setTransport($config);
        $transport = $this->transport;
        $attributes = array_filter($transport->getAttributes());
        $attributes['sign'] = parent::generateSignature($attributes, $this->partner_key);
        $post = $this->xml($attributes);
        $response = $this->curl_post_ssl(self::REFUND_QUERY_URL, $post);
        return $this->parseRequestXml($response);
    }

    const MMPAYMKTTRANSFERS_URL = '/mmpaymkttransfers/promotion/transfers';

    /**
     * 向微信用户个人付款 
     * @param array $config
     * ```
     * [
     *     'device_info' => '', // 设备号 	device_info 	否 	013467007045764 	String(32) 	微信支付分配的终端设备号
     *     'nonce_str' => '', // 随机字符串 	nonce_str 	是 	5K8264ILTKCH16CQ2502SI8ZNMTM67VS 	String(32) 	随机字符串，不长于32位
     *     'sign' => '', // 签名 	sign 	是 	C380BEC2BFD727A4B6845133519F3AD6 	String(32) 	签名，详见签名算法
     *     'partner_trade_no' => '', // 商户订单号 	partner_trade_no 	是 	10000098201411111234567890 	String(32) 	商户订单号，需保持唯一性(只能是字母或者数字，不能包含有其它字符)
     *     'openid' => '', // 用户openid 	openid 	是 	oxTWIuGaIt6gTKsQRLau2M0yL16E 	String(64) 	商户appid下，某用户的openid
     *     'check_name' => '', // 校验用户姓名选项 	check_name 	是 	FORCE_CHECK 	String(16) 	NO_CHECK：不校验真实姓名FORCE_CHECK：强校验真实姓名
     *     're_user_name' => '', // 收款用户姓名 	re_user_name 	否 	王小王 	String(64) 	收款用户真实姓名。如果check_name设置为FORCE_CHECK，则必填用户真实姓名如需电子回单，需要传入收款用户姓名
     *     'amount' => '', // 金额 	amount 	是 	10099 	int 	企业付款金额，单位为分
     *     'desc' => '', // 企业付款备注 	desc 	是 	理赔 	String(100) 	企业付款备注，必填。注意：备注中的敏感词会被转成字符*
     *     'spbill_create_ip' => '', // Ip地址 	spbill_create_ip 	否 	192.168.0.1 	String(32) 	该IP同在商户平台设置的IP白名单中的IP没有关联，该IP可传用户端或者服务端的IP。
     * ]
     * ```
     * @return type
     */
    public function brokerage($config) {
        if (!isset($config['class'])) {
            $config['class'] = Mmpaymkttransfers::class;
        }
        //申请商户号的appid或商户号绑定的appid
        $config['mch_appid'] = $this->appid;
        //微信支付分配的商户号
        $config['mchid'] = $this->mch_id;

        Yii::error($config);

        $this->setTransport($config, false);
        $attributes = array_filter($this->transport->getAttributes());
        $attributes['sign'] = parent::generateSignature($attributes, $this->partner_key);
        $post = $this->xml($attributes);
        Yii::error($post);
        $response = $this->curl_post_ssl(self::MMPAYMKTTRANSFERS_URL, $post);
        return $this->parseRequestXml($response);
    }

}
